﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

using System.Windows.Threading;

namespace Acl.WinFormHosting.Internal;


sealed class WinFormsThread
{
    private readonly ManualResetEventSlim serviceManualResetEvent = new(false);
    private readonly IHostApplicationLifetime hostApplicationLifetime;
    private IWinFormsContext UiContext;
    private IServiceProvider ServiceProvider;

    public WinFormsThread(IServiceProvider serviceProvider)
    {
        UiContext = serviceProvider.GetRequiredService<IWinFormsContext>();
        hostApplicationLifetime = serviceProvider.GetRequiredService<IHostApplicationLifetime>();
        ServiceProvider = serviceProvider;
        var newUiThread = new Thread(InternalUiThreadStart)
        {
            IsBackground = true,
        };
        newUiThread.SetApartmentState(ApartmentState.STA);
        newUiThread.Start();
    }

    public void Start() =>
        // 唤醒UI 线程执行消息循环
        serviceManualResetEvent.Set();

    private void InternalUiThreadStart()
    {
        PreUiThreadStart();
        serviceManualResetEvent.Wait();
        UiContext.IsRunning = true;
        UiThreadStart();
    }



    private void PreUiThreadStart()
    {
        Dispatcher currentDispatcher = Dispatcher.CurrentDispatcher;
        UiContext.Dispatcher = currentDispatcher;
        SynchronizationContext.SetSynchronizationContext((SynchronizationContext?)new DispatcherSynchronizationContext(currentDispatcher));
        if (UiContext.EnableVisualStyles)
        {
            Application.EnableVisualStyles();
        }

        Application.SetHighDpiMode(UiContext.HighDpiMode);
        Application.SetCompatibleTextRenderingDefault(UiContext.CompatibleTextRenderingDefault);
        Application.ApplicationExit += OnApplicationExit;
    }

    /// <summary>
    /// 启动Windows Forms 应用程序
    /// </summary>
    private void UiThreadStart()
    {
        var winFormServices = ServiceProvider.GetServices<IWinFormsService>();
        foreach (var winFormService in winFormServices)
        {
            winFormService.Initialize();
        }

        var shells = ServiceProvider.GetServices<IMainForm>().Cast<Form>().ToArray();

        switch (shells.Length)
        {
            case 1:
                Application.Run(shells[0]);
                break;
            case 0:
                Application.Run();
                break;
            default:
                var multiShellContext = new MultiShellContext(shells);
                Application.Run(multiShellContext);
                break;
        }
    }

    private void OnApplicationExit(object? sender, EventArgs eventArgs)
    {
        Application.ApplicationExit -= OnApplicationExit;
        HandleApplicationExit();
    }

    private void HandleApplicationExit()
    {
        UiContext.IsRunning = false;
        if (!UiContext.IsLifetimeLinked)
        {
            return;
        }

        if (hostApplicationLifetime.ApplicationStopped.IsCancellationRequested || hostApplicationLifetime.ApplicationStopping.IsCancellationRequested)
        {
            return;
        }
        hostApplicationLifetime.StopApplication();
    }
}
